home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Graphics⁄Sound
/
RTrace-1.0-src
/
shade.c
< prev
next >
Wrap
Text File
|
1992-08-17
|
5KB
|
166 lines
/*
* Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
* All rights reserved.
*
* This code received contributions from the following people:
*
* Roman Kuchkuda - basic ray tracer
* Mark VandeWettering - MTV ray tracer
* Augusto Sousa - overall, shading model
* Paul Strauss - shading model
* Craig Kolb - textures
* David Buck - textures
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Antonio Costa, at INESC-Norte. The name of the author and
* INESC-Norte may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "defs.h"
#include "extern.h"
/**********************************************************************
* RAY TRACING - Shade - Version 7.0 *
* *
* MADE BY : Antonio Costa, INESC-Norte, October 1988 *
* ADAPTED BY : Antonio Costa, INESC-Norte, June 1989 *
* MODIFIED BY: Antonio Costa, INESC-Norte, October 1991 *
**********************************************************************/
/***** Shading *****/
boolean
refract(ray, normal, inside, refraction)
ray_ptr ray;
xyz_ptr normal;
boolean inside;
real refraction;
{
REG real k0, k1, ratio;
k0 = -DOT_PRODUCT(ray->vector, *normal); /* Incidence angle cosine */
if (ABS(k0) < ROUNDOFF)
return FALSE;
if (inside)
ratio = refraction; /* Leaving object */
else
ratio = 1.0 / refraction; /* Entering object */
k1 = 1.0 - SQR(ratio) * (1.0 - SQR(k0));
if (k1 >= ROUNDOFF)
{
k1 = ratio * k0 - SQRT(k1);
/* Refracted ray */
ray->vector.x = ratio * ray->vector.x + k1 * normal->x;
ray->vector.y = ratio * ray->vector.y + k1 * normal->y;
ray->vector.z = ratio * ray->vector.z + k1 * normal->z;
return TRUE;
}
return FALSE;
}
void
make_diffuse_vector(normal, result)
xyz_ptr normal, result;
{
real a1, sin_a1_sin_a2, cos_a1_sin_a2, sin_a2, cos_a2;
xyz_struct u, v;
cos_a2 = SQRT(RANDOM);
sin_a2 = SQRT(1.0 - SQR(cos_a2));
a1 = 2 * PI * RANDOM;
sin_a1_sin_a2 = SIN(a1) * sin_a2;
cos_a1_sin_a2 = COS(a1) * sin_a2;
v.x = 1.0;
v.y = 0.0;
v.z = 0.0;
if (ABS(DOT_PRODUCT(*normal, v)) > 1.0 - ROUNDOFF)
{
v.y = 1.0;
v.x = 0.0;
}
CROSS_PRODUCT(u, *normal, v);
NORMALIZE(u);
CROSS_PRODUCT(v, u, *normal);
result->x = u.x * cos_a1_sin_a2 + v.x * sin_a1_sin_a2 + normal->x * cos_a2;
result->y = u.y * cos_a1_sin_a2 + v.y * sin_a1_sin_a2 + normal->y * cos_a2;
result->z = u.z * cos_a1_sin_a2 + v.z * sin_a1_sin_a2 + normal->z * cos_a2;
NORMALIZE(*result);
}
void
make_specular_vector(reflected, normal, factor, result)
xyz_ptr reflected, normal, result;
real factor;
{
real a1, sin_a1_sin_a2, cos_a1_sin_a2, sin_a2, cos_a2;
xyz_struct u, v;
do
{
cos_a2 = POWER(SQRT(RANDOM), factor + 1.0);
sin_a2 = SQRT(1.0 - SQR(cos_a2));
a1 = 2 * PI * RANDOM;
sin_a1_sin_a2 = SIN(a1) * sin_a2;
cos_a1_sin_a2 = COS(a1) * sin_a2;
v.x = 1.0;
v.y = 0.0;
v.z = 0.0;
if (ABS(DOT_PRODUCT(*reflected, v)) > 1.0 - ROUNDOFF)
{
v.y = 1.0;
v.x = 0.0;
}
CROSS_PRODUCT(u, *reflected, v);
NORMALIZE(u);
CROSS_PRODUCT(v, u, *reflected);
result->x = u.x * cos_a1_sin_a2 + v.x * sin_a1_sin_a2 +
reflected->x * cos_a2;
result->y = u.y * cos_a1_sin_a2 + v.y * sin_a1_sin_a2 +
reflected->y * cos_a2;
result->z = u.z * cos_a1_sin_a2 + v.z * sin_a1_sin_a2 +
reflected->z * cos_a2;
NORMALIZE(*result);
} while (DOT_PRODUCT(*result, *normal) < ROUNDOFF);
}
int
estimate_diffuse(n, d)
int n;
real d;
{
return ROUND((real) n * d);
}
int
estimate_specular(n, s, f)
int n;
real s, f;
{
#define S_THRESHOLD (0.5)
if (s < S_THRESHOLD)
return ROUND((real) n * s);
else
return ROUND((real) n / (1.0 + f) * (s + f / (1.0 - S_THRESHOLD) *
(S_THRESHOLD - S_THRESHOLD * s)));
#undef S_THRESHOLD
}
void
shade(position, normal, ray, object, color)
xyz_ptr position, normal; /* Normal may be modified */
ray_ptr ray;
object_ptr object;
rgb_ptr color;
{
switch (shade_mode)
{
case 0:
shade_phong(position, normal, ray, object, color);
break;
case 1:
shade_strauss(position, normal, ray, object, color);
break;
}
}